package seabattle.ship;

import seabattle.field.BattleField;
import seabattle.field.Cell;
import seabattle.field.FieldEditable;

public class ShipsGenerator {
    private FieldEditable field;
    public final int MAX_SHIP_SIZE = 4;
    private ShipGenerator generator;

    public ShipsGenerator(ShipGenerator generator) {
        this.generator = generator;
    }

    public void generateOn(FieldEditable field) {
        this.field = field;
        for (int shipSize = MAX_SHIP_SIZE; shipSize > 0; shipSize--) {
            for (int shipAmount = MAX_SHIP_SIZE - shipSize + 1; shipAmount > 0; shipAmount--) {
                Ship ship = createShip(shipSize);
                field.addShip(ship);
            }
        }
    }

    private Ship createShip(int shipSize) {
        boolean setShip;
        Ship ship;
        do {
            ship = generator.generate(shipSize);
            setShip = verifyPossibleLocation(ship);
        } while (!setShip);
        return ship;
    }

    private boolean verifyPossibleLocation(Ship ship) {
        int x = ship.getDisposal().getX();
        int y = ship.getDisposal().getY();
        for (int index = 0; index < ship.getLength(); index++) {
            if (ship.getDirection().isVertical()) {
                boolean verifyOk = verifyPossiblePutDeck(new Coordinates(x, y + index));
                if (!verifyOk) {
                    return false;
                }
            } else {
                boolean verifyOk = verifyPossiblePutDeck(new Coordinates(x + index, y));
                if (!verifyOk) {
                    return false;
                }
            }
        }
        return true;
    }

    private boolean verifyPossiblePutDeck(Coordinates coordinates) {
        int x = coordinates.getX();
        int y = coordinates.getY();
        for (int deltaX = x - 1; deltaX < x + 2; deltaX++) {
            if ((deltaX < 0) || (deltaX > BattleField.SIZE - 1)) {
                continue;
            }
            for (int deltaY = y - 1; deltaY < y + 2; deltaY++) {
                if ((deltaY < 0) || (deltaY > BattleField.SIZE - 1)) {
                    continue;
                }
                if (field.getCell(deltaX, deltaY) != Cell.EMPTY) {
                    return false;
                }
            }
        }
        return true;
    }

}
